// Copyright (c) 2016  David Muse
// All rights reserved.
//
// This code is marked CONFIDENTIAL.

#ifndef FWPK_NAME
	#error Please define FWPK_NAME before including fwpk.h
#endif

#ifndef FWPK_KEY_LOCATION
	#error Please define FWPK_KEY_LOCATION before including fwpk.h
#endif

{
#if 0
goto tests;
fail:
	stdoutput.printf("Invalid product key for \"%s\"\n(%s)\n",
					FWPK_NAME,FWPK_KEY_LOCATION);
	process::exit(1);

tests:

// read the key from the file
file	keyfile;
if (!keyfile.open(FWPK_KEY_LOCATION,O_RDONLY)) {
	goto fail;
}
unsigned char key[20];
if (keyfile.read(key,19)!=19) {
	goto fail;
}
key[19]='\0';

debugPrintf("product key: %s\n",key);

// split the key
key[4]='\0';
key[9]='\0';
key[14]='\0';
unsigned char	*keypart1=key;
unsigned char	*keypart2=key+5;
unsigned char	*keypart3=key+10;
unsigned char	*keypart4=key+15;

debugPrintf("product key parts: %s %s %s %s\n",
		keypart1,keypart2,keypart3,keypart4);

// name or date test
if (keypart4[3]=='5') {

	// date test...

	// get the rotation factor
	int32_t	rot=10-(key[0]-'0');
	debugPrintf("rotation factor: %d\n",10-rot);

	// get the epoch time
	uint64_t	epoch=0;
	uint64_t	factor=1;
	for (uint16_t i=1; i<15; i++) {

		// skip dashes
		if (i==4 || i==9 || i==14) {
			continue;
		}

		// unrotate the number and add it to the epoch time
		epoch+=((key[i]-'0'+rot)%10)*factor;

		// bump the factor
		factor*=10;
	}

	debugPrintf("epoch time %lld\n",epoch);
	debugPrintf("current time %lld\n",(uint64_t)time(NULL));

	// (lrc of key part 1) % 10
	unsigned char	lrc=0;
	for (const unsigned char *c=keypart1; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	debugPrintf("lrc%10 of %s: %c\n",keypart1,(lrc%10)+'0');
	if (keypart4[0]!=(lrc%10)+'0') {
		stdoutput.printf("Invalid product key for %s\n",FWPK_NAME);
		process::exit(1);
	}

	// (lrc of key part 2) % 10
	lrc=0;
	for (const unsigned char *c=keypart2; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	debugPrintf("lrc%10 of %s: %c\n",keypart2,(lrc%10)+'0');
	if (keypart4[1]!=(lrc%10)+'0') {
		goto fail;
	}

	// (lrc of key part 3) % 10
	lrc=0;
	for (const unsigned char *c=keypart3; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	debugPrintf("lrc%10 of %s: %c\n",keypart3,(lrc%10)+'0');
	if (keypart4[2]!=(lrc%10)+'0') {
		goto fail;
	}

	if (epoch<time(NULL)) {
		goto fail;
	}

} else {

	// name test...

	// get lrc of FWPK_NAME
	unsigned char	lrc=0;
	for (const unsigned char *c=(const unsigned char *)FWPK_NAME; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	
	debugPrintf("lrc of \"%s\": %03d\n",FWPK_NAME,lrc);

	// get lrc as 3 characters
	unsigned char	lrc1=(lrc%10)+'0';
	lrc/=10;
	unsigned char	lrc10=(lrc%10)+'0';
	lrc/=10;
	unsigned char	lrc100=(lrc%10)+'0';

	debugPrintf("lrc of \"%s\" (as 3 characters): %c %c %c\n",
					FWPK_NAME,lrc100,lrc10,lrc1);

	// (lrc of key part 1 + lrc100) % 10
	lrc=0;
	for (const unsigned char *c=keypart1; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(lrc+lrc100)&0xff;
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	debugPrintf("lrc%10 of %s and %c: %c\n",keypart1,lrc100,(lrc%10)+'0');
	if (keypart4[0]!=(lrc%10)+'0') {
		stdoutput.printf("Invalid product key for %s\n",FWPK_NAME);
		process::exit(1);
	}

	// (lrc of key part 2 + lrc10) % 10
	lrc=0;
	for (const unsigned char *c=keypart2; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(lrc+lrc10)&0xff;
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	debugPrintf("lrc%10 of %s and %c: %c\n",keypart2,lrc10,(lrc%10)+'0');
	if (keypart4[1]!=(lrc%10)+'0') {
		goto fail;
	}

	// (lrc of key part 3 + lrc10) % 10
	lrc=0;
	for (const unsigned char *c=keypart3; *c; c++) {
		lrc=(lrc+*c)&0xff;
	}
	lrc=(lrc+lrc1)&0xff;
	lrc=(((lrc^0xff)+1)&0xff);
	lrc=(lrc<128)?lrc:(lrc-128);
	debugPrintf("lrc%10 of %s and %c: %c\n",keypart3,lrc1,(lrc%10)+'0');
	if (keypart4[2]!=(lrc%10)+'0') {
		goto fail;
	}

	// (part4[0] + part4[1] + part4[2]) % 10 (5->4)
	unsigned char	last=((keypart4[0]+keypart4[1]+keypart4[2])%10);
	if (last==5) {
		last=4;
	}
	debugPrintf("sum(lrcs)%10 (5->4): %c\n",last+'0');
	if (keypart4[3]!=last+'0') {
		goto fail;
	}
}
#endif
}
